package lime.agent;

import java.util.*;

import emulator.peers.*;
import emulator.agent.*;

import eventengine.middleware.*;

import tuplespace.tuples.*;

import lime.middleware.*;

public class AgentLimeEXP extends AgentLime
{
 static int BOOT_DELAY = 5;
 static boolean REALTIME_SCREEN_UPDATE = true;
 LimeInterface lime;
 private AgentLimeGui frame;

 private PeerInterface_ApplicationSide peer;

 Vector perceivedLocalTuples = new Vector();
 Vector perceivedRemoteTuples = new Vector();

 private EventInterface tsEvent;
 private EventInterface vtsEvent;

 public AgentLimeEXP(PeerInterface_ApplicationSide peer)
 {
  this.peer = peer;
  //lime = (LimeInterface)new limefast.middleware.LimeFast(peer);
  lime = (LimeInterface)new Lime(peer);
  frame = new AgentLimeGui(this, peer.toString());


  /* create event server and make subsciptions to the lime middleware to get
  notified about tupels being inserted and removed */
  tsEvent = new EventServer("AgentLime"+peer.toString()+"TS");
  vtsEvent = new EventServer("AgentLime"+peer.toString()+"VTS");
  lime.setOutsideEvent(tsEvent, vtsEvent);

  TsTuple in = new TsTuple("<op=IN><tuple=*>");
  TsTuple out = new TsTuple("<op=OUT><tuple=*>");

  tsEvent.subscribe(in,this,"LOCAL_IN");
  tsEvent.subscribe(out,this,"LOCAL_OUT");

  vtsEvent.subscribe(in,this,"REMOTE_IN");
  vtsEvent.subscribe(out,this,"REMOTE_OUT");
 }

 public String toString()
 {
  return new String("agentLime on "+lime.toString());
 }

 /*****************************************************************************/
 /*                            AGENT OWN ACTIONS                              */
 /*****************************************************************************/
 public void write (String content)
 {
  Tuple t = (Tuple)new Tuple(content);
  lime.write(t);
 }

 public void extract (String content)
 {
  Tuple t = new Tuple(content);
  lime.extract(t);
 }

 public void keyextract (String content)
 {
  Tuple t = new Tuple(content);
  lime.keyextr(t);
 }

 /*****************************************************************************/
 /*                          REACTIVE METHOD                                  */
 /*****************************************************************************/
 public void react(String reaction, String event)
 {
  if(reaction.equalsIgnoreCase("LOCAL_IN"))
  {
   TsTuple ts = (TsTuple)Tuple.deserialize(event);
   Tuple t = Tuple.deserialize(ts.tuple);
   perceivedLocalTuples.add(t);
  }
  else if(reaction.equalsIgnoreCase("LOCAL_OUT"))
  {
   TsTuple ts = (TsTuple)Tuple.deserialize(event);
   Tuple t = Tuple.deserialize(ts.tuple);
   perceivedLocalTuples.remove(t);
  }
  else if(reaction.equalsIgnoreCase("REMOTE_IN"))
  {
   TsTuple ts = (TsTuple)Tuple.deserialize(event);
   Tuple t = Tuple.deserialize(ts.tuple);
   perceivedRemoteTuples.add(t);
  }
  else if(reaction.equalsIgnoreCase("REMOTE_OUT"))
  {
   TsTuple ts = (TsTuple)Tuple.deserialize(event);
   Tuple t = Tuple.deserialize(ts.tuple);
   perceivedRemoteTuples.remove(t);
  }
 }

 /*****************************************************************************/
 /*                          AGENT INTERFACE METHODS                          */
 /* These metohds wouldn't be actually required by the real agents that simply
 would display this panel in their user interface. However they are needed for
 /*****************************************************************************/
 public void step(int time)
 {
  if(time == BOOT_DELAY)
  {
   /* init the tulpes' arrays */
   Tuple all = new Tuple("<content=*>");
   perceivedLocalTuples = lime.read(all);
   perceivedRemoteTuples = lime.rdOneHop(all);
  }

  lime.step(time);
  if(REALTIME_SCREEN_UPDATE)
   frame.updateGUI();
 }

 public synchronized void showAgentFrame()
 {
  frame.show();
 }
 public synchronized void hideAgentFrame()
 {
  frame.hide();
  peer.shutDown();
 }

 public synchronized Object getRealIdentity()
 {
  return this;
 }
}